﻿using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Thinktecture.IdentityServer.Core.Models;
using Thinktecture.IdentityServer.Core.Services;

namespace IdSrv.Config
{

        /// <summary>
        /// In-memory token handle store
        /// </summary>
        public class MyCustomTokenHandleStore : ITokenHandleStore
        {
            readonly ConcurrentDictionary<string, Token> _repository = new ConcurrentDictionary<string, Token>();
            /// <summary>
            /// Stores the data.
            /// </summary>
            /// <param name="key">The key.</param>
            /// <param name="value">The value.</param>
            /// <returns></returns>
            public Task StoreAsync(string key, Token value)
            {
                _repository[key] = value;
                return Task.FromResult<object>(null);
            }
            /// <summary>
            /// Retrieves the data.
            /// </summary>
            /// <param name="key">The key.</param>
            /// <returns></returns>
            public Task<Token> GetAsync(string key)
            {
                Token token;
                if (_repository.TryGetValue(key, out token))
                {
                    return Task.FromResult(token);
                }
                return Task.FromResult<Token>(null);
            }
            /// <summary>
            /// Removes the data.
            /// </summary>
            /// <param name="key">The key.</param>
            /// <returns></returns>
            public Task RemoveAsync(string key)
            {
                Token token;
                _repository.TryRemove(key, out token);
                return Task.FromResult<object>(null);
            }
            /// <summary>
            /// Retrieves all data for a subject identifier.
            /// </summary>
            /// <param name="subject">The subject identifier.</param>
            /// <returns>
            /// A list of token metadata
            /// </returns>
            public Task<IEnumerable<ITokenMetadata>> GetAllAsync(string subject)
            {
                var query =
                from item in _repository
                where item.Value.SubjectId == subject
                select item.Value;
                var list = query.ToArray();
                return Task.FromResult(list.Cast<ITokenMetadata>());
            }
            /// <summary>
            /// Revokes all data for a client and subject id combination.
            /// </summary>
            /// <param name="subject">The subject.</param>
            /// <param name="client">The client.</param>
            /// <returns></returns>
            public Task RevokeAsync(string subject, string client)
            {
                var query =
                from item in _repository
                where item.Value.SubjectId == subject && item.Value.ClientId == client
                select item.Key;
                foreach (var key in query)
                {
                    RemoveAsync(key);
                }
                return Task.FromResult(0);
            }
        }
    }